package com.huilian.iotbox.client.service.pay;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.huilian.iotbox.aliyun.service.PubService;
import com.huilian.iotbox.client.service.*;
import com.huilian.iotbox.client.service.UserService;
import com.huilian.iotbox.data.common.RedisHelper;
import com.huilian.iotbox.data.common.RedisKey;
import com.huilian.iotbox.data.common.ServerResponse;
import com.huilian.iotbox.data.config.AgencyConfig;
import com.huilian.iotbox.data.config.MiddlewareConfig;
import com.huilian.iotbox.data.controller.ControllerException;
import com.huilian.iotbox.data.dto.*;
import com.huilian.iotbox.data.enums.*;
import com.huilian.iotbox.data.exception.SysException;
import com.huilian.iotbox.data.po.*;
import com.huilian.iotbox.data.properties.ConfigProperties;
import com.huilian.iotbox.data.service.*;
import com.huilian.iotbox.data.utils.HttpUtils;
import com.huilian.iotbox.data.utils.HttpsMain;
import com.huilian.iotbox.data.vo.*;
import com.huilian.tool.common.config.AppletAliConfig;
import com.huilian.tool.common.config.AppletDouYinConfig;
import com.huilian.tool.common.config.AppletWeChatConfig;
import com.huilian.tool.douyin.applet.service.DouYinAppletPayService;
import com.huilian.tool.douyin.applet.service.DouYinAppletService;
import com.huilian.tool.douyin.enums.DouYinOrderStatusEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.Serializable;
import java.math.BigDecimal;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * AbstractPayService
 *
 * @Author mineChen
 * @Date 2021/12/20 上午 11:23
 */

@Slf4j
public abstract class AbstractPayService implements PayService {

    @Value("${huilian.iot.productKey}")
    private String productKey;
    @Autowired
    private PubService pubService;
    @Autowired
    private UserService userService;
    @Autowired
    private RedisHelper redisHelper;
    @Autowired
    private RetryService retryService;
    @Autowired
    private AgencyConfig agencyConfig;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private AgencyService agencyService;
    @Autowired
    private AppletAliConfig appletAliConfig;
    @Autowired
    public ConfigProperties configProperties;
    @Autowired
    private AppletDouYinConfig appletDouYinConfig;
    @Autowired
    private AppletWeChatConfig appletWeChatConfig;
    @Autowired
    private LedgerOrderSerivce ledgerOrderService;
    @Autowired
    private DouYinAppletService douYinAppletService;
    @Autowired
    private MerchantStoreService merchantStoreService;
    @Autowired
    private LedgerMerchantSerivce ledgerMerchantSerivce;
    @Autowired
    private ErrorLogCommonService errorLogCommonService;
    @Autowired
    private DouYinAppletPayService douYinAppletPayService;
    @Autowired
    private RedisTemplate<String, Serializable> redisCacheTemplate;
    @Autowired
    private MemberStoreBalanceCommonService memberStoreBalanceCommonService;
    @Autowired
    private AppletOrOfficialAccountCommonService appletOrOfficialAccountCommonService;
    @Autowired
    private CommodityPurchaseRestrictionCommonService commodityPurchaseRestrictionCommonService;
    @Autowired
    private ShareCommonService shareCommonService;
    /**
     * 验证
     *
     * @param orderDto
     * @param memberId
     * @throws ParseException
     */
    @Override
    public void verification(OrderDto orderDto, Long memberId) throws ParseException {

        String storeKey = String.format(RedisKey.MERCHANT_STORE, orderDto.getMerchantStoreId());
        MerchantStore merchantStore = (MerchantStore) redisCacheTemplate.opsForValue().get(storeKey);
        if (StringUtils.isEmpty(merchantStore)) {
            MerchantStore store = new MerchantStore();
            store.setId(orderDto.getMerchantStoreId());
            merchantStore = merchantStoreService.findMerchantStore(store);
            if (ObjectUtils.isEmpty(merchantStore)) {
                throw new SysException(ErrorMsgEnum.MERCHANT_STORE_NOT_FOUND.getMsg());
            } else if (ObjectUtils.isEmpty(merchantStore.getMerchantId())) {
                throw new SysException(ErrorMsgEnum.MERCHANT_STORE_NOT_ASSOCIATED_MERCHANT.getMsg());
            }
            redisCacheTemplate.opsForValue().set(storeKey, merchantStore, 1, TimeUnit.HOURS);
        }
        orderDto.setMchType(MchTypeEnum.OWN.getCode());

        UserVo u = userService.findUser(merchantStore.getUserId());
        if (StringUtils.isEmpty(u)) {
            throw new SysException("运营商不存在");
        }
        if (u.getLockStatus()) {
            throw new SysException("该设备代理商已被冻结！设备暂时无法使用！");
        }

        if (!StringUtils.isEmpty(memberId)) {
            // 商户会员信息
            MemberStoreBalanceDto memberStoreBalanceDto = new MemberStoreBalanceDto();
            memberStoreBalanceDto.setMerchantStoreId(orderDto.getMerchantStoreId());
            memberStoreBalanceDto.setMemberId(memberId);
            MemberStoreBalanceVo memberStoreBalanceVo = memberStoreBalanceCommonService.findBalance(memberStoreBalanceDto);
            if (StringUtils.isEmpty(memberStoreBalanceVo)) {
                memberStoreBalanceCommonService.add(memberId, orderDto.getMerchantStoreId(), merchantStore.getUserId(), orderDto.getDeviceNo());
                memberStoreBalanceVo = memberStoreBalanceCommonService.findBalance(memberStoreBalanceDto);
                if (StringUtils.isEmpty(memberStoreBalanceVo)) {
                    throw new SysException("会员未关联场地");
                }
            }

            orderDto.setRechargeBeforeBalance(memberStoreBalanceVo.getRechargeBalance() + memberStoreBalanceVo.getDonateBalance());
            orderDto.setRechargeAfterBalance(orderDto.getRechargeBeforeBalance());

            orderDto.setFunction(OrderFunctionEnum.OFFICIAL.getStatus());
        } else {
            // 区分反扫付款码类型
            orderDto.setFunction(OrderFunctionEnum.REVERSE_SCAN.getStatus());
            orderDto.setAuthCode(orderDto.getQrCodeUrl());
        }

        // 判断门店是否冻结
        if (merchantStore.getStatus() != null) {
            if (StoreStatusEnum.LOCKED.getCode().equals(merchantStore.getStatus())) {
                throw new SysException("该门店被冻结，无法支付");
            }
        }

        // 查看商户是否被冻结
        final UserVo userVo = userService.findUser(merchantStore.getUserId());
        if (userVo.getLockStatus()) {
            throw new SysException("商家账号被冻结，无法支付");
        }

        // 查询商户是否选择收款类型
        String key = String.format(RedisKey.RECEIPT_TYPE, merchantStore.getUserId());
        String receiptType = (String) redisCacheTemplate.opsForValue().get(key);
        if (receiptType == null) {
            if (userVo.getReceiptType() != null) {
                redisCacheTemplate.opsForValue().set(key, userVo.getReceiptType().toString());
                receiptType = userVo.getReceiptType().toString();
            } else {
                throw new SysException("商家还未选择收款类型，暂不能支付");
            }
        }

        // 判断营业时间
        if (merchantStore.getBusinessStartTime() != null && merchantStore.getBusinessEndTime() != null) {
            this.operationTime(merchantStore);
        }

        // 活动-系统订单号
        orderDto.setOutTradeNo(HttpUtils.getOutTradeNo());
        // 活动-支付订单号
        orderDto.setPayOrderNo(HttpUtils.getOutTradeNo());
        orderDto.setMemberId(memberId); //135827

        // 计算支付优惠
        if (!StringUtils.isEmpty(merchantStore.getDiscountStatus())) {
            if (merchantStore.getDiscountStatus()) {
                BigDecimal preferentialAmount = orderDto.getTotalAmount().multiply(merchantStore.getMaxDiscountRate());
                if (preferentialAmount.compareTo(orderDto.getDiscountMoney()) > 0) {
                    orderDto.setDiscountMoney(orderDto.getDiscountMoney());
                    orderDto.setTotalAmount(orderDto.getTotalAmount().subtract(orderDto.getDiscountMoney()));
                }
            }
        }
        if (ChannelTypeEnum.WX.getStr().equalsIgnoreCase(orderDto.getChannelType())) {
            orderDto.setChannelType(ChannelTypeEnum.WX.getCode());
        } else if (ChannelTypeEnum.Ali.getStr().equalsIgnoreCase(orderDto.getChannelType())) {
            orderDto.setChannelType(ChannelTypeEnum.Ali.getCode());
        } else if (ChannelTypeEnum.DOUYIN.getStr().equalsIgnoreCase(orderDto.getChannelType())) {
            orderDto.setChannelType(ChannelTypeEnum.DOUYIN.getCode());
        }
        orderDto.setUserId(merchantStore.getUserId());
        orderDto.setMerchantId(merchantStore.getMerchantId());
        orderDto.setPayCompanyCode(merchantStore.getPayCompanyCode());
        orderDto.setStatus(OrderStatusEnum.WAIT.getCode());
    }

    /**
     * 设备验证
     *
     * @param device
     * @throws ParseException
     */
    @Override
    public void deviceVerification(DeviceDto device, OrderDto orderDto) {
        if (StringUtils.isEmpty(device)) {
            // 找不到设备
            throw new SysException(ErrorMsgEnum.DEVICE_NOT_FOUND.getMsg());
        }

        orderDto.setDeviceTypeId(device.getDeviceTypeId());
        orderDto.setDeviceNo(device.getDeviceNo());

        if (StringUtils.isEmpty(device.getNetworkIntensity()) || device.getNetworkIntensity() <= 0) {
            // 没信号或信号等于0
            throw new SysException(String.format(ErrorMsgEnum.DEVICE_OFLINE.getMsg(), device.getDeviceNo()));
        }
        if (!ObjectUtils.isEmpty(device.getStatus())) {
            // 设备不是上架状态
            if (DeviceStatusEnum.OFF_LINE.getCode().equals(device.getStatus())) {
                // 下架
                throw new SysException(String.format(ErrorMsgEnum.DEVICE_OFF_LINE.getMsg(), device.getDeviceNo()));
            } else if (DeviceStatusEnum.FAULT.getCode().equals(device.getStatus())) {
                // 故障
                throw new SysException(String.format(ErrorMsgEnum.DEVICE_FAULT.getMsg(), device.getDeviceNo()));
            } else if (DeviceStatusEnum.NON_ACTIVATED.getCode().equals(device.getStatus())) {
                // 未激活
                throw new SysException(String.format(ErrorMsgEnum.DEVICE_NON_ACTIVATED.getMsg(), device.getDeviceNo()));
            } else if (DeviceStatusEnum.UNBIND.getCode().equals(device.getStatus())) {
                // 未绑定
                throw new SysException(String.format(ErrorMsgEnum.DEVICE_UNBIND.getMsg(), device.getDeviceNo()));
            }
        } else {
            throw new SysException(String.format(ErrorMsgEnum.DEVICE_FAULT.getMsg(), device.getDeviceNo()));
        }

        // 兑币机的时候防止同时支付
        if (DeviceTypeEnum.CONVERTIBLE_CURRENCY_MACHINE.getCode().equals(device.getDeviceTypeId()) || DeviceTypeEnum.SUPER_MONEY_CHANGER.getCode().equals(device.getDeviceTypeId())) {
            String memberPayKey = String.format(RedisKey.PREVENT_SIMULTANEOUS_PAYMENT, device.getId());
            log.info("orderDto.getMemberId():" + orderDto.getMemberId());
            String memberPayDetailKey = String.format(RedisKey.PREVENT_SIMULTANEOUS_PAYMENT_DETAIL, device.getId(), orderDto.getMemberId());
            log.info("memberPayKey:" + memberPayKey);
            log.info("memberPayDetailKey:" + memberPayDetailKey);

            Set<String> keys = redisHelper.keys(memberPayKey + "*");
            log.info("keys：" + keys.toString());
            // true：存在当前
            boolean existMemberPayDetailKey = false;
            for (String key : keys) {
                log.info("key-detail：" + key);
                if (memberPayDetailKey.equals(key)) {
                    existMemberPayDetailKey = true;
                }
            }

            if (keys.size() > 1 || (!existMemberPayDetailKey && keys.size() == 1)) {
                throw new RuntimeException("有顾客正在支付，请稍等");
            } else {
                redisCacheTemplate.opsForValue().set(memberPayDetailKey, orderDto.getMemberId(), 15, TimeUnit.SECONDS);
            }
        }
    }

    @Override
    public Object reqPay(OrderDto orderDto, MemberDto memberDto) throws IOException, NoSuchAlgorithmException, NoSuchProviderException, KeyManagementException {
        //查询套餐限购
        if (!StringUtils.isEmpty(orderDto.getDiscountId()) || !StringUtils.isEmpty(orderDto.getCommodityStoreUpDownId())) {
            CommodityPurchaseRestrictionDto commodityPurchaseRestrictionDto = new CommodityPurchaseRestrictionDto();
            commodityPurchaseRestrictionDto.setMemberId(memberDto.getId());
            if (!StringUtils.isEmpty(orderDto.getDiscountId())) {
                commodityPurchaseRestrictionDto.setCommodityStoreUpDownId(orderDto.getDiscountId());
            } else if (!StringUtils.isEmpty(orderDto.getCommodityStoreUpDownId())) {
                commodityPurchaseRestrictionDto.setCommodityStoreUpDownId(orderDto.getCommodityStoreUpDownId());
            }
            commodityPurchaseRestrictionDto.setQuantity(1);
            commodityPurchaseRestrictionCommonService.checkCommodityPurchaseRestrictionBuy(commodityPurchaseRestrictionDto);
        }

        // 限制每分钟,每小时,每天的支付笔数和支付金额
        merchantStoreService.getMemberRisk(memberDto.getId(), orderDto.getMerchantStoreId());

        BigDecimal totalAmount = orderDto.getTotalAmount().multiply(new BigDecimal("100")).setScale(0, BigDecimal.ROUND_HALF_UP);
        Map<String, Object> form = new HashMap<>();
        form.put("outTradeNo", orderDto.getOutTradeNo());

        MerchantStoreVo merchantStoreVo =null;
        AppletOrOfficialAccount appletOrOfficialAccount = null;
        if (StringUtils.isEmpty(orderDto.getPaymentEnvironment()) || orderDto.getPaymentEnvironment().compareTo(1) == 0) {
            // H5支付
            if (StringUtils.isEmpty(merchantStoreVo.getDedicatedOfficialAccount())) {
                form.put("WxAppId", MiddlewareConfig.WX_APPID);
                log.info("支付_1，默认微信公众号APPID");
            } else {
                appletOrOfficialAccount = appletOrOfficialAccountCommonService.findOneById(merchantStoreVo.getDedicatedOfficialAccount());
                if (StringUtils.isEmpty(appletOrOfficialAccount)) {
                    throw new RuntimeException("专属公众号配置信息为空_1，请联系平台处理");
                }
                form.put("WxAppId", appletOrOfficialAccount.getOfficialAccountAppId());
                log.info("支付_1，专属微信公众号：" + appletOrOfficialAccount.getId());
            }
        } else if (orderDto.getPaymentEnvironment().compareTo(2) == 0) {
            // 微信小程序支付
            form.put("PayType", "AppPayApplet");
            if (StringUtils.isEmpty(merchantStoreVo.getDedicatedWeChatApplet())) {
                form.put("WxAppId", appletWeChatConfig.getAppId());
                log.info("支付_1，默认微信小程序APPID");
            } else {
                appletOrOfficialAccount = appletOrOfficialAccountCommonService.findOneById(merchantStoreVo.getDedicatedWeChatApplet());
                if (StringUtils.isEmpty(appletOrOfficialAccount)) {
                    throw new RuntimeException("专属微信小程序配置信息为空_1，请联系平台处理");
                }
                form.put("WxAppId", appletOrOfficialAccount.getWeChatAppId());
                log.info("支付_1，专属微信小程序：" + appletOrOfficialAccount.getId());
            }
        } else if (orderDto.getPaymentEnvironment().compareTo(3) == 0) {
            // 支付宝小程序支付
            form.put("PayType", "AppPayApplet");
            if (StringUtils.isEmpty(merchantStoreVo.getDedicatedALiApplet())) {
                form.put("WxAppId", appletAliConfig.getAppId());
                log.info("支付_1，默认支付宝小程序APPID");
            } else {
                appletOrOfficialAccount = appletOrOfficialAccountCommonService.findOneById(merchantStoreVo.getDedicatedALiApplet());
                if (StringUtils.isEmpty(appletOrOfficialAccount)) {
                    throw new RuntimeException("专属支付宝小程序配置信息为空_1，请联系平台处理");
                }
                form.put("WxAppId", appletOrOfficialAccount.getALiAppId());
                log.info("支付_2，专属支付宝小程序：" + appletOrOfficialAccount.getId());
            }
        } else if (orderDto.getPaymentEnvironment().compareTo(4) == 0) {
            // 抖音小程序支付
            return this.reqDouYinPay(orderDto.getOutTradeNo(), totalAmount.intValue(), orderDto.getBody());
        }
        //抖音、美团抽佣使用
        JsPay jsPay = shareCommonService.divideAccounts(LedgerOrderTypeEnum.ORDER.getCode(), orderDto.getTotalAmount(), orderDto.getUserId(), orderDto.getMerchantStoreId(), orderDto.getMerchantId(), orderDto.getId());
        if (!ObjectUtils.isEmpty(jsPay)) {
            //分账串
            form.put("splitBunch", jsPay.getSplitBunch());
        }

        form.put("Body", orderDto.getBody());
        form.put("HlMerchantId", orderDto.getMerchantId());

        StringBuffer sucUrl = new StringBuffer(configProperties.getDevicePayQrUrl());
        sucUrl.append(orderDto.getDeviceNo());
        if (StringUtils.isEmpty(orderDto.getPaymentEnvironment()) || orderDto.getPaymentEnvironment().compareTo(1) == 0) {
            if (!StringUtils.isEmpty(orderDto.getAgencyId())) {
                final Agency agency = agencyService.getAgencyById(orderDto.getAgencyId());
                if (!StringUtils.isEmpty(agency) && !StringUtils.isEmpty(agency.getDedicatedOfficialAccount())) {
                    AppletOrOfficialAccount aooa = appletOrOfficialAccountCommonService.findOneById(agency.getDedicatedOfficialAccount());
                    if (!StringUtils.isEmpty(aooa) && !StringUtils.isEmpty(aooa.getOfficialAccountUrl())) {
                        sucUrl = new StringBuffer(aooa.getOfficialAccountUrl());
                        sucUrl.append("/c?d=");
                        sucUrl.append(orderDto.getDeviceNo());
                    }
                }
            }
        }

        if (!StringUtils.isEmpty(orderDto.getHierarchy()) && !StringUtils.isEmpty(orderDto.getFreightLane())) {
            sucUrl.append("&h=");
            sucUrl.append(orderDto.getHierarchy());
            sucUrl.append("&f=");
            sucUrl.append(orderDto.getFreightLane());
        }

        form.put("SucUrl", sucUrl);

        form.put("TotalAmount", totalAmount);
        if (ChannelTypeEnum.WX.getCode().equalsIgnoreCase(orderDto.getChannelType())) {
            if (StringUtils.isEmpty(orderDto.getPaymentEnvironment()) || orderDto.getPaymentEnvironment().compareTo(1) == 0) {
                // H5支付取公众号openId
                form.put("OpenId", memberDto.getOfficialAccountOpenId());
            } else {
                form.put("OpenId", memberDto.getOpenId());
            }
            orderDto.setChannelType(ChannelTypeEnum.WX.getStr());
        } else if (ChannelTypeEnum.Ali.getCode().equalsIgnoreCase(orderDto.getChannelType())) {
            form.put("OpenId", memberDto.getZfbUserId()); //2088022000006691
            orderDto.setChannelType(ChannelTypeEnum.Ali.getStr());
        }
        form.put("NotifyUrl", configProperties.getClientBackEndUrl() + "/api/order/payNotice");
        JSONObject jsonObject = new JSONObject();
        if (!ObjectUtils.isEmpty(orderDto.getPrivateDomainOperationScoreId())) {
            log.info("查看赠币券ID的数据：{}", orderDto.getPrivateDomainOperationScoreId());
            // 赠币券ID
            jsonObject.put("privateDomainOperationScoreId", orderDto.getPrivateDomainOperationScoreId());
        }
        if (!StringUtils.isEmpty(orderDto.getFunction())) {
            log.info("携带参数function：{}", orderDto.getFunction());
            jsonObject.put("function", orderDto.getFunction());
        }
        if (!StringUtils.isEmpty(orderDto.getPayNo())) {
            log.info("携带参数payNo：{}", orderDto.getPayNo());
            jsonObject.put("payNo", orderDto.getPayNo());
        }
        form.put("attach", jsonObject.toJSONString());

        form.put("ChannelType", orderDto.getChannelType());
        // 给支付系统标识是否显隐跳转按钮
        form.put("deviceId", orderDto.getDeviceNo() + "_iotbox_1");
        log.info("参数JSON{}", form);
        String param = HttpUtils.format(agencyConfig, form, FunctionEnum.JS_PAY);
        String response = HttpsMain.httpsReq(MiddlewareConfig.reqUrl + "/pay", param);
        log.info("请求响应结果{}", response);
        //延签并返回map值
        final Map<String, Object> result = HttpUtils.getResultData(response);
        final String status = (String) result.get("status");
        final String code = (String) result.get("code");
        if (status.equals(RequestStatus.SUCCESS.getCode()) && code.equals(RequestStatus.SUCCESS_CODE.getCode())) {
            Object data = result.get("data");
            JSONObject dataJsonObject = JSON.parseObject(data.toString());
            dataJsonObject.remove("agencyNo");
            dataJsonObject.remove("function");
            dataJsonObject.remove("hlMerchantId");
            dataJsonObject.remove("orderNo");
            dataJsonObject.remove("outTradeNo");
            return dataJsonObject;
        } else {
            String msg = (String) result.get("msg");
            if (msg.indexOf("当前服务商因存在违规") != -1) {
                throw new SysException("当前商家暂不支持支付宝支付，请使用微信扫码支付");
            } else if (msg.indexOf("微信认证") != -1) {
                throw new SysException("请商家完成微信认证");
            } else if (msg.indexOf("支付宝认证") != -1) {
                throw new SysException("请商家完成支付宝认证");
            } else {
                throw new SysException((String) result.get("msg"));
            }
        }
    }

    /**
     * 抖音预下单（支付准备）
     *
     * @param outTradeNo
     * @param totalAmount
     * @param body
     * @return
     * @throws IOException
     */
    @Override
    public Object reqDouYinPay(String outTradeNo, int totalAmount, String body) throws IOException {
        JSONObject jsonObject = douYinAppletPayService.orderInAdvance(
                outTradeNo,
                totalAmount,
                body,
                300,
                configProperties.getClientBackEndUrl() + "/api/order/douyin/pay/notify"
        );
        Integer errNo = jsonObject.getIntValue("err_no");
        if (errNo.compareTo(0) == 0) {
            return jsonObject.getJSONObject("data");
        }
        errorLogCommonService.writerInfoErrorLog("抖音预下单不成功", jsonObject);
        return ServerResponse.createByErrorMessage("预下单不成功，请联系平台");
    }

    /**
     * 反扫付款码支付
     *
     * @param orderDto
     * @param request
     * @return
     * @throws IOException
     * @throws NoSuchAlgorithmException
     * @throws ParseException
     */
    @Override
    public synchronized ServerResponse reverseScanReqPay(OrderDto orderDto, HttpServletRequest request) throws IOException, NoSuchAlgorithmException, NoSuchProviderException, KeyManagementException {

        BigDecimal totalAmount = orderDto.getTotalAmount().multiply(new BigDecimal("100")).setScale(0, BigDecimal.ROUND_HALF_UP);
        Map<String, Object> form = new HashMap<>();
        form.put("outTradeNo", orderDto.getOutTradeNo());
        form.put("body", "付款码支付：" + orderDto.getBody());
        form.put("hlMerchantId", orderDto.getMerchantId());
        form.put("totalAmount", totalAmount);
        form.put("deviceId", orderDto.getDeviceNo());
        form.put("authCode", orderDto.getAuthCode());
        form.put("NotifyUrl", configProperties.getClientBackEndUrl() + "/api/order/payNotice");
        JsPay jsPay = shareCommonService.divideAccounts(LedgerOrderTypeEnum.ORDER.getCode(), orderDto.getTotalAmount(), orderDto.getUserId(), orderDto.getMerchantStoreId(), orderDto.getMerchantId(), orderDto.getId());

        if (!ObjectUtils.isEmpty(jsPay)) {
            //分账串
            form.put("splitBunch", jsPay.getSplitBunch());
        }

        JSONObject jsonObject = new JSONObject();
        if (!StringUtils.isEmpty(orderDto.getPayNo())) {
            log.info("携带参数payNo：{}", orderDto.getPayNo());
            jsonObject.put("payNo", orderDto.getPayNo());
        }
        form.put("attach", jsonObject.toJSONString());
        String param = HttpUtils.format(agencyConfig, form, FunctionEnum.PAY_CODE_PAY);
        String response = HttpsMain.httpsReq(MiddlewareConfig.reqUrl + "/pay", param);
        log.info("请求响应结果{}", response);

        final Map<String, Object> result = HttpUtils.getResultData(response);
        final String resStatus = (String) result.get("status");
        final String resMsg = (String) result.get("msg");

        if ("F".equals(resStatus) || "1".equals(resStatus) || (resMsg != null && resMsg.contains("失败"))) {
            log.error("请求中间件付款码支付失败：{}", resMsg);
            if (org.apache.commons.lang.StringUtils.isNotEmpty(resMsg) && (resMsg.indexOf("authCode不在指定范围内") > -1 || resMsg.indexOf("字符串规则校验失败") > -1)) {
                throw new RuntimeException("识别失败，请重新扫码");
            }
            throw new RuntimeException(resMsg);
        }
        Object data = result.get("data");
        JSONObject jsonData = JSONObject.parseObject(data.toString());
        JSONObject orderVo = new JSONObject();
        orderVo.put("outTradeNo", jsonData.getString("outTradeNo"));
        //0:fail  1:paying 2:succ
        orderVo.put("tradeStatus", jsonData.getString("tradeStatus"));
        orderVo.put("resMsg", resMsg);
        return ServerResponse.createBySuccess(orderVo);
    }

    // 判断经营时间
    private void operationTime(MerchantStore merchantStore) throws ParseException {
        Calendar calendar = null;
        calendar = Calendar.getInstance();
        calendar.add(Calendar.HOUR_OF_DAY, 0);
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        String date = sdf.format(calendar.getTime());
//     log.info("进入：{}",sdf.format(calendar.getTime()));
        Date time = sdf.parse(date);
        String start = merchantStore.getBusinessStartTime();
        String end = merchantStore.getBusinessEndTime();
//
        Date businessStartTime = sdf.parse(start);
        Date businessEndTime = sdf.parse(end);
        // 如果开始时间和结束时间相等，就代表没有时间限制
        if (!businessStartTime.equals(businessEndTime)) {
            // 判断如果开始时间比结束时间大，那么代表结束时间是第二天凌晨  如果开始时间小于结束时间，那么代表结束时间按照正常的24小时的时间来判断就行了
            if (businessStartTime.after(businessEndTime)) {
                // 因为结束时间是第二天凌晨，所以判断结束时间就行
                if (time.after(businessEndTime)) {
                    // 如果不在结束时间内，就判断是否在开始时间内
                    if (time.before(businessStartTime)) {
                        throw new ControllerException("非营业时间，请在营业时间" + start + "至" + end + "前来交易");
                    }
                    // 当前时间不是凌晨所以判断开始时间就行了
                } else if (time.before(businessStartTime)) {
                    if (time.after(businessEndTime)) {
                        throw new ControllerException("非营业时间，请在营业时间" + start + "至" + end + "前来交易");
                    }
                }
            } else {
                if (time.after(businessStartTime) && time.before(businessEndTime)) {
                } else {
                    throw new ControllerException("非营业时间，请在营业时间" + start + "至" + end + "前来交易");
                }
            }
        }
    }

    @Override
    public void orderGen(OrderDto orderDto, DeviceDto device, HttpServletRequest request) throws IOException, NoSuchAlgorithmException {
        log.info("默认orderGen");
    }

    @Override
    public void orderGen(OrderDto orderDto, HttpServletRequest request) {
        log.info("默认orderGen");
    }
}
